package com.xbongbong.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.EnableEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.paas.model.ContractCompareModel;
import com.xbongbong.paas.model.ContractCompareUserModel;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.pojo.vo.ContractCompareDetailVO;
import com.xbongbong.paas.pojo.vo.ContractCompareVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.thread.TransmittableThreadLocalUtil;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.UrlConstant;
import com.xbongbong.pro.contractCompare.pojo.ComparePoJo;
import com.xbongbong.pro.contractCompare.pojo.ContractCompareUrlPojo;
import com.xbongbong.pro.contractCompare.pojo.dto.ContractCompareDTO;
import com.xbongbong.pro.contractCompare.pojo.dto.ContractCompareListDTO;
import com.xbongbong.pro.customer.pojo.dto.Base64DecodeMultipatrFile;
import com.xbongbong.pro.domain.entity.ContractCompareUserEntity;
import com.xbongbong.pro.enums.ContractCompareFeeStatusEnum;
import com.xbongbong.pro.enums.ContractCompareUrlOpenEnum;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.PackageTypeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.TimeTypeEnum;
import com.xbongbong.pro.enums.ValueAddedTypeEnum;
import com.xbongbong.pro.enums.errorcodes.ContractCompareErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.menu.enums.ContractCompareMenuEnum;
import com.xbongbong.pro.enums.menu.enums.SystemAppMenuEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.packageInfo.pojo.vo.BasePackageInfoVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.ContractCompareStatusEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ContractCompareEnum;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.domain.entity.FeeLogEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.FeeLogModel;
import com.xbongbong.sys.model.UserModel;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.xbongbong.paas.elasticsearch.constant.EsNormalConstant.MINI_MUM_SHOULD_MATCH;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchPhraseQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author zhushuainan
 * @title: ContractCompareUtil
 * @projectName xbb-pro
 * @description: 合同比对工具类
 * @date 2022/11/17 13:53
 */
@Component
public class ContractCompareUtil {

    private static final Logger LOG = LoggerFactory.getLogger(ContractCompareUtil.class);

    /**
     * 图片类型常量，可以手动添加
     */
    private static String[] imageType = {"jpg", "jpeg", "png", "tif", "tiff"};

    @Resource
    private FeeLogModel feeLogModel;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private UserModel userModel;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private ContractCompareModel contractCompareModel;
    @Resource
    private ContractCompareUserModel contractCompareUserModel;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private PackageHelp packageHelp;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private PaasMenuModel paasMenuModel;


    /**
     * 获取套餐状态
     *
     * @param corpid
     * @return
     */
    public Integer getContractCompareStatus(String corpid) {
        String key = corpid + StringConstant.COLON + CompanyConfigEnum.CONTRACT_COMPARE_KEY.getAlias();
        String value = paasRedisHelper.getValue(RedisConstant.KEY_COMPANY_CONFIG, key);
        if (Objects.isNull(value)) {
            CompanyConfigEntity companyConfig = companyConfigModel.getByConfigAlias(CompanyConfigEnum.CONTRACT_COMPARE_KEY.getAlias(), corpid);
            if (Objects.isNull(companyConfig)) {
                return ContractCompareFeeStatusEnum.NO_TRIAL.getType();
            } else {
                paasRedisHelper.setValue(RedisConstant.KEY_COMPANY_CONFIG, key, companyConfig.getConfigValue(), TimeConstant.SECONDS_PER_DAY);
            }
        }
        List<FeeLogEntity> feeLogList = feeLogModel.getByType(corpid, ValueAddedTypeEnum.CONTRACT_COMPARE.getType());
        if (feeLogList.isEmpty()) {
            return ContractCompareFeeStatusEnum.TRIAL.getType();
        }
        long now = DateUtil.getNow();
        FeeLogEntity feeLogEntity = feeLogList.stream().max(Comparator.comparing(FeeLogEntity::getEndTime)).orElse(null);
        if (feeLogEntity.getEndTime() < now) {
            return ContractCompareFeeStatusEnum.OVERDUE.getType();
        }
        int sum = feeLogList.stream().mapToInt(FeeLogEntity::getSumValue).sum();
        Integer totalUsed= getTotalCount(corpid);
        if (totalUsed >= sum){
            return ContractCompareFeeStatusEnum.USEUP.getType();
        }
        return ContractCompareFeeStatusEnum.OFFICIAL.getType();
    }



    public List<ContractCompareDetailVO> getDataList(ContractCompareListDTO contractCompareListDTO, ContractCompareVO contractCompareVO) throws XbbException {
        try {
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            //解析查询条件
            JSONObject conditionJson = contractCompareListDTO.getCommonFilter();
            if (Objects.nonNull(conditionJson)) {
                for (String key : conditionJson.keySet()) {
                    if (Objects.equals(key, ContractCompareEnum.ADD_TIME.getSaasAttr()) && Objects.nonNull(conditionJson.get(key))) {
                        JSONArray addTime = JSONObject.parseArray(JSONObject.toJSONString(conditionJson.get(key)));
                        boolQueryBuilder.filter(rangeQuery(key).gte(DateTimeUtil.getInt(addTime.getString(0) + " 00:00:00", DateTimeUtil.SDF)).lte(DateTimeUtil.getInt(addTime.getString(1) + " 23:59:59", DateTimeUtil.SDF)));
                    } else if (Objects.equals(key, ContractCompareEnum.FORM_TYPE.getSaasAttr())) {
                        boolQueryBuilder.filter(termQuery(key, conditionJson.get(key)));
                    } else {
                        if (!StringUtil.isEmpty((String) conditionJson.get(key))) {
                            boolQueryBuilder.filter(termQuery(key + ".keyword", conditionJson.get(key)));
                        }
                    }
                }
            }
            List<ConditionsEntityExt> conditionList = contractCompareListDTO.getConditions();
            //解析数据权限条件
            for (ConditionsEntityExt conditionsEntityExt : conditionList) {
                if (Objects.equals(conditionsEntityExt.getAttr(), ContractCompareEnum.CREATOR_ID.getSaasAttr())) {
                    boolQueryBuilder.filter(termsQuery(conditionsEntityExt.getAttr()+ StringConstant.POINT + StringConstant.KEY_WORD, conditionsEntityExt.getValue()));
                } else {
                    boolQueryBuilder.filter(termsQuery(conditionsEntityExt.getAttr(), conditionsEntityExt.getValue()));
                }
            }

            if (!StringUtil.isEmpty(contractCompareListDTO.getValue())) {
                QueryBuilder queryBuilder = QueryBuilders.matchPhraseQuery(contractCompareListDTO.getAttr(), contractCompareListDTO.getValue());
                BoolQueryBuilder shouldBool = boolQuery();
                shouldBool.should(queryBuilder);
                shouldBool.should(termQuery(contractCompareListDTO.getAttr() + StringConstant.POINT + StringConstant.KEY_WORD, contractCompareListDTO.getValue()));
                shouldBool.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
                boolQueryBuilder.filter(shouldBool);
            }
            String nameLike = contractCompareListDTO.getNameLike();
            if (!StringUtil.isEmpty(nameLike)) {
                boolQueryBuilder.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
                boolQueryBuilder.should(matchPhraseQuery(ContractCompareEnum.STANDARD_CONTRACT_NAME.getSaasAttr(), nameLike));
                boolQueryBuilder.should(matchPhraseQuery(ContractCompareEnum.STANDARD_CONTRACT_NAME.getSaasAttr() + StringConstant.POINT + StringConstant.KEY_WORD, nameLike));
                boolQueryBuilder.should(matchPhraseQuery(ContractCompareEnum.STANDARD_CONTRACT_FILE.getSaasAttr(), nameLike));
                boolQueryBuilder.should(matchPhraseQuery(ContractCompareEnum.STANDARD_CONTRACT_FILE.getSaasAttr() + StringConstant.POINT + StringConstant.KEY_WORD, nameLike));
                boolQueryBuilder.should(matchPhraseQuery(ContractCompareEnum.COMPARE_CONTRACT_NAME.getSaasAttr(), nameLike));
                boolQueryBuilder.should(matchPhraseQuery(ContractCompareEnum.COMPARE_CONTRACT_NAME.getSaasAttr() + StringConstant.POINT + StringConstant.KEY_WORD, nameLike));
                boolQueryBuilder.should(matchPhraseQuery(ContractCompareEnum.COMPARE_CONTRACT_FILE.getSaasAttr(), nameLike));
                boolQueryBuilder.should(matchPhraseQuery(ContractCompareEnum.COMPARE_CONTRACT_FILE.getSaasAttr() + StringConstant.POINT + StringConstant.KEY_WORD, nameLike));
            }
            boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, contractCompareListDTO.getCorpid()));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            sourceBuilder.query(boolQueryBuilder);
            //排序
            SortOrder order = SortOrder.DESC;
            String sortField = "updateTime";
            Map<String, String> sortMap = contractCompareListDTO.getSortMap();
            if (sortMap != null && !sortMap.isEmpty()) {
                sortField = (StringUtil.isEmpty(sortMap.get("field")) ? sortField : sortMap.get("field"));
                if (!sortField.equals(ContractCompareEnum.ADD_TIME.getSaasAttr()) && !sortField.equals(ContractCompareEnum.COMPARE_STATUS.getSaasAttr()) && !sortField.equals(ContractCompareEnum.FORM_TYPE.getSaasAttr()) && !sortField.equals("updateTime")) {
                    sortField += ".raw";
                }
                if (SortOrder.ASC.toString().equals(sortMap.get("sort"))) {
                    order = SortOrder.ASC;
                }
            }
            sourceBuilder.sort(new FieldSortBuilder(sortField).order(order));
            sourceBuilder.sort(new FieldSortBuilder("id").order(SortOrder.ASC));
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, contractCompareListDTO.getPage(), contractCompareListDTO.getPageSize());
            SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_CONTRACT_COMPARE.getIndex());
            searchRequest.source(sourceBuilder);
            XbbAggregatedPage<ContractCompareDetailVO> xbbAggregatedPage = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, ContractCompareDetailVO.class);
            List<ContractCompareDetailVO> contractCompareDetailVOList = xbbAggregatedPage.getContent();
            PageHelper pageHelper = new PageHelper(contractCompareListDTO.getPage(), contractCompareListDTO.getPageSize());
            pageHelper.setRowsCount((int) xbbAggregatedPage.getTotalElements());
            contractCompareVO.setPageHelper(pageHelper);
            return contractCompareDetailVOList;
        } catch (Exception e) {
            LOG.error(contractCompareListDTO.getCorpid() + "es查询出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }



    public String contractCompare(ContractCompareDTO contractCompareDTO) throws XbbException{
        String url = "https://doc-compare.intsig.com/doc_compare/create";
        String key = contractCompareDTO.getCorpid() + StringConstant.COLON + CompanyConfigEnum.CONTRACT_COMPARE_KEY.getAlias();
        String value = paasRedisHelper.getValue(RedisConstant.KEY_COMPANY_CONFIG, key);
        CompanyConfigEntity companyConfig = new CompanyConfigEntity();
        if (Objects.isNull(value)) {
            companyConfig = companyConfigModel.getByConfigAlias(CompanyConfigEnum.CONTRACT_COMPARE_KEY.getAlias(), contractCompareDTO.getCorpid());
            if (Objects.isNull(companyConfig)) {
                throw new XbbException(ContractCompareErrorCodeEnum.API_ERROR_1620010);
            } else {
                paasRedisHelper.setValue(RedisConstant.KEY_COMPANY_CONFIG, key, companyConfig.getConfigValue(), TimeConstant.SECONDS_PER_DAY);
            }
        } else {
            companyConfig.setConfigValue(value);
        }

        JSONObject configValue = JSONObject.parseObject(companyConfig.getConfigValue());
        String result = "";
        OutputStreamWriter out = null;
        BufferedReader in = null;
        try {
            String param = "{\"mode\":\"deprecated\",\"convert_arg\":{\"remove_stamp\":%s,\"remove_comments\":%s,\"remove_footnote\":0,\"remove_headerfooter\":%s,\"remove_symbol\":%s,\"merge_diff\":0},\"config\":{\"engine\":\"table\",\"use_pdf_parser\":\"true\"}}";
            Integer removeComments = 0;
            Integer removeHeaderfooter = 0;
            Integer removeStamp = 0;
            Integer removeSymbol = 0;
            for (String compareSetting : contractCompareDTO.getCompareSettingList()) {
                if (Objects.equals("removeComments", compareSetting)) {
                    removeComments=1;
                    continue;
                }
                if (Objects.equals("removeHeaderfooter", compareSetting)) {
                    removeHeaderfooter=1;
                    continue;
                }
                if (Objects.equals("removeStamp", compareSetting)) {
                    removeStamp=1;
                    continue;
                }
                if (Objects.equals("removeSymbol", compareSetting)) {
                    removeSymbol=1;
                    continue;
                }
            }
            param = String.format(param, removeComments, removeHeaderfooter, removeStamp, removeSymbol);
            JSONObject paramJson = JSONObject.parseObject(param);
            List<ComparePoJo> files = contractCompareDTO.getCompareList();
            for (int i = 0; i < files.size(); i++) {
                String fileUrl = files.get(i).getFileUrl();
                String fileBase64 = Base64DecodeMultipatrFile.requestUrlToBase64(fileUrl);
                String ext = fileUrl.substring(fileUrl.lastIndexOf('.') + 1);
                JSONArray jsonArray = new JSONArray();
                JSONObject jsonObject = new JSONObject();
                String fileName = files.get(i).getFileName();
                if (Arrays.asList(imageType).contains(ext)) {
                    JSONArray fileDataArray = new JSONArray();
                    fileDataArray.add(fileBase64);
                    jsonObject.put("filedata", fileDataArray);
                    //三方API要求图片类型的文件后缀名必须是.imgs
                    jsonObject.put("filename", fileName.substring(0, fileName.lastIndexOf('.')) + ".imgs");
                    jsonArray.add(jsonObject);
                    if (i==0) {
                        //默认第一个文件是标准文档
                        paramJson.put("standard_doc", jsonArray);
                    } else{
                        paramJson.put("compare_doc", jsonArray);
                    }
                } else {
                    jsonObject.put("filedata", fileBase64);
                    jsonObject.put("filename", fileName);
                    jsonArray.add(jsonObject);
                    if (i==0) {
                        //默认第一个文件是标准文档
                        paramJson.put("standard_doc", jsonArray);
                    } else{
                        paramJson.put("compare_doc", jsonArray);
                    }
                }
            }
            URL realUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
            conn.setRequestProperty("app-key", configValue.getString("key"));
            conn.setRequestProperty("app-secret", configValue.getString("secret"));
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("content-Type", "application/json");
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.connect();
            out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
            out.append(paramJson.toJSONString());
            out.flush();
            out.close();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            LOG.error(contractCompareDTO.getCorpid() + e);
            throw new XbbException(ContractCompareErrorCodeEnum.API_ERROR_1620013);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

    /**
        * @description: 获取用量
        * @param corpid
        * @param type 时间类型枚举： 每天，月；
        * @return java.lang.Integer
        * @author zhushuainan
        * @date 2022/11/24 10:04:22
        */
    public Integer getDayOrMonthConsumption(String corpid, TimeTypeEnum type){
        long startTime = Objects.equals(type, TimeTypeEnum.DAY) ? DateTimeUtil.getTodayInt() : DateTimeUtil.getFirstDateOfThisMonth();
        long endTime = DateTimeUtil.getInt();

        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put("compareStatus", ContractCompareStatusEnum.SUCCESS.getCode());
        param.put("startUseTime", startTime);
        param.put("endUseTime", endTime);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        Integer count = contractCompareModel.getEntityCount(param);
        return count;
    }

    public Long getDeadLine(String corpid){
        List<Integer> feeTypeIn = Collections.singletonList(ValueAddedTypeEnum.CONTRACT_COMPARE.getType());
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put("feeTypeIn",feeTypeIn);
        List<FeeLogEntity> feeLogEntitys = feeLogModel.findEntitys(param);
        Long deadline = feeLogEntitys.get(0).getEndTime();
        for (FeeLogEntity feeLogEntity : feeLogEntitys) {
            Long endTime = feeLogEntity.getEndTime();
            if (deadline < endTime){
                deadline = endTime;
            }
        }
        return deadline;
    }


    public Integer getTotalCount(String corpid){
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put("compareStatus",0);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        Integer count = contractCompareModel.getEntityCount(param);
        return count;
    }

    public void pageSet(Integer page, Integer size, Map<String, Object> param) {
        size = Objects.isNull(size) ? 20 : size;
        param.put(StringConstant.PAGE_SIZE, size);
        page = Objects.isNull(page) ? 1 : page;
        int start = page <= 1 ? 0 : (page - 1) * size;
        param.put(StringConstant.START, start);
    }

    public Integer getContractCompareStaff(String corpid, String userId){
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put("userId",userId);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        List<ContractCompareUserEntity> entitys = contractCompareUserModel.findEntitys(param);
        return CollectionsUtil.isNotEmpty(entitys) ? entitys.get(0).getStaff() : 0;
    }

    public Boolean showCompareButton(String corpid, Set<String> permSet, String userId) throws XbbException {
        BasePackageInfoVO basePackageInfoVO = packageHelp.getBasePackageInfoFromRedis(corpid);
        //试用版或者免费版不暴露按钮
        if (Objects.equals(basePackageInfoVO.getFeeType(), PackageTypeEnum.FREE.getType()) || basePackageInfoVO.getFeeEndTime() < DateUtil.getTodayInt()) {
            return false;
        }
        Integer compareStatus = getContractCompareStatus(corpid);
        boolean isOfficial = false;
        if (!Objects.equals(compareStatus, ContractCompareFeeStatusEnum.TRIAL.getType()) && !Objects.equals(compareStatus, ContractCompareFeeStatusEnum.NO_TRIAL.getType())){
            isOfficial = true;
        }
        PaasAppEntity contractCompareApp = paasAppModel.getByAlias(SystemAppMenuEnum.CONTRACT_COMPARE.getAlias(), corpid);
        //contractCompareApp为null,说明还没有合同比对的应用,还没进行第一次比对,暴露按钮 未开启坐席不展示按钮
        if (Objects.isNull(contractCompareApp) || (Objects.equals(contractCompareApp.getEnable(), EnableEnum.OPEN.getCode()) && !isOfficial)) {
            return true;
        }
        Integer staff = getContractCompareStaff(corpid, userId);
        if (Objects.equals(contractCompareApp.getEnable(), EnableEnum.OPEN.getCode()) && permSet.contains(ProPermissionAliasEnum.CONTRACT_COMPARE_RESULT_ADD.getAlias()) && Objects.equals(BasicConstant.ONE, staff)) {
            return true;
        }

        return false;
    }

    public Boolean showCompareTab(String corpid, Set<String> permSet, String userId) throws XbbException {
        BasePackageInfoVO basePackageInfoVO = packageHelp.getBasePackageInfoFromRedis(corpid);
        //试用版或者免费版不暴露按钮
        if (Objects.equals(basePackageInfoVO.getFeeType(), PackageTypeEnum.FREE.getType()) || basePackageInfoVO.getFeeEndTime() < DateUtil.getTodayInt()) {
            return false;
        }
        Integer compareStatus = getContractCompareStatus(corpid);
        boolean isOfficial = false;
        if (!Objects.equals(compareStatus, ContractCompareFeeStatusEnum.TRIAL.getType()) && !Objects.equals(compareStatus, ContractCompareFeeStatusEnum.NO_TRIAL.getType())){
            isOfficial = true;
        }
        PaasAppEntity contractCompareApp = paasAppModel.getByAlias(SystemAppMenuEnum.CONTRACT_COMPARE.getAlias(), corpid);
        if (Objects.isNull(contractCompareApp)){
            return false;
        }
        //contractCompareApp为null,说明还没有合同比对的应用,还没进行第一次比对,暴露按钮 未开启坐席不展示按钮
        if (Objects.equals(contractCompareApp.getEnable(), EnableEnum.OPEN.getCode()) && !isOfficial) {
            return true;
        }
        Integer staff = getContractCompareStaff(corpid, userId);
        if (Objects.equals(contractCompareApp.getEnable(), EnableEnum.OPEN.getCode()) && permSet.contains(ProPermissionAliasEnum.CONTRACT_COMPARE_RESULT_ADD.getAlias()) && Objects.equals(BasicConstant.ONE, staff)) {
            return true;
        }

        return false;
    }

    /**
     * 获取cmr url 查看权限
     * @param corpid
     * @param contractCompareId 合同比对结果id
     * @param userVO 登陆人
     * @param urlOpenSource {@link ContractCompareUrlOpenEnum}
     * @return
     * @throws XbbException
     */
    public Boolean getShowCrmUrlPermission(String corpid, Long contractCompareId, UserVO userVO, Integer urlOpenSource) throws XbbException {
        if (userVO.isAdminOrBoss()) {
            return true;
        }

        Set<String> permSet = userVO.getPermSet();
        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(userVO, userEntity);
        boolean validPermission;
        ContractCompareUrlOpenEnum compareUrlOpenEnum = ContractCompareUrlOpenEnum.getByCode(urlOpenSource);
        if (Objects.equals(ContractCompareUrlOpenEnum.START_COMPARE, compareUrlOpenEnum)) {
            validPermission = permSet.contains(ProPermissionAliasEnum.CONTRACT_COMPARE_RESULT_VIEW.getAlias()) || permSet.contains(ProPermissionAliasEnum.CONTRACT_COMPARE_RESULT_ADD.getAlias());
        } else {
            validPermission = permSet.contains(ProPermissionAliasEnum.CONTRACT_COMPARE_RESULT_VIEW.getAlias());
        }
        if (!validPermission) {
            LOG.info("合同比对crm url: 无查看权限，合同比对结果id={}", contractCompareId);
            return false;
        }

        PaasMenuEntity paasMenuEntity = paasMenuModel.getByAlias(ContractCompareMenuEnum.CONTRACT_COMPARE_RESULT.getAlias(), corpid);
        TransmittableThreadLocalUtil.setValue(SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CONTRACT_COMPARE_RESULT.getCode(), paasMenuEntity.getId(), DistributorMarkEnum.OTHER.getCode());

        if (userVO.isMaxDataPermission()) {
            return true;
        }

        Integer dataPermission = userModel.getDataPermission(userEntity);
        List<String> userIdIn = userModel.getSubIdListByDataPermission(dataPermission, userEntity.getUserId(), userEntity.getCorpid(), BasicConstant.ZERO, false);

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();

        boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termsQuery(StringConstant.CREATOR_ID + StringConstant.POINT + StringConstant.KEY_WORD, userIdIn));
        boolQueryBuilder.filter(termQuery(StringConstant.ID, contractCompareId));

        sourceBuilder.query(boolQueryBuilder);
        EsUtil.setPage(sourceBuilder, 1, 1);
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_CONTRACT_COMPARE.getIndex());
        searchRequest.source(sourceBuilder);
        CountRequest countRequest = new CountRequest(searchRequest.indices()[0]);
        countRequest.query(searchRequest.source().query());
        long count = xbbElasticsearchRestTemplate.count(countRequest);

        return count > BasicConstant.ZERO;
    }

    /**
     * 封装合同比对结果的Crm url
     * @param contractCompareUrlPojo
     * @return
     */
    public String packagingCompareResultUrlToCrmUrl(ContractCompareUrlPojo contractCompareUrlPojo) {
        if (Objects.nonNull(contractCompareUrlPojo)) {
            String secret = JSON.toJSONString(contractCompareUrlPojo);
            String encodeSecret = getEncodeSecret(secret);

            String webFrontUrl = proBaseConfig.getWebFrontUrl();
            String crmUrlSuffix = UrlConstant.ContractCompareUrl.CRM_URL_SUFFIX;
            // https://pt2webf.xbongbong.com.cn/#/contract?secret=xxxx
            return String.format(webFrontUrl + crmUrlSuffix, encodeSecret);
        }
        return null;
    }

    /**
     * 根据加密secret获取解密secret
     * @param encodeSecret
     * @return
     */
    public String getDecodeSecret(String encodeSecret) {
        if (StringUtil.isNotEmpty(encodeSecret)) {
            Base64.Decoder decoder = Base64.getUrlDecoder();
            byte[] decode = decoder.decode(encodeSecret);
            return new String(decode);
        }
        return encodeSecret;
    }

    /**
     * 加密secret
     * @param secret
     * @return
     */
    public String getEncodeSecret(String secret) {
        if (StringUtil.isNotEmpty(secret)) {
            Base64.Encoder encoder = Base64.getUrlEncoder();
            return new String(encoder.encode(secret.getBytes()));
        }
        return secret;
    }
}
